package com.lakeworks.framework.interceptor;

import com.lakeworks.domain.SysChannelAuth;
import com.lakeworks.service.ISysChannelAuthService;
import org.apache.commons.codec.digest.HmacUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.StringJoiner;
import java.util.UUID;

import static java.lang.String.format;
import static java.util.Objects.isNull;
import static org.apache.commons.codec.binary.Base64.encodeBase64String;
import static org.apache.commons.codec.digest.HmacAlgorithms.HMAC_SHA_256;
import static org.apache.commons.lang3.StringUtils.*;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;

/**
 * @Author: Auxps
 * @Date: 2023/3/3
 * Description:
 * 三方渠道 认证拦截器
 */
@Component
public class AuthorizationInterceptor implements ClientHttpRequestInterceptor {

    private static final String VERSION = "1.0";

    private static final String PREFIX = "channel";

    private static final Logger log = LoggerFactory.getLogger(AuthorizationInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        HttpHeaders headers = request.getHeaders();
        headers.keySet().forEach(headName -> {
            if (headName.equals(AUTHORIZATION) && headers.get(headName).get(0).startsWith(PREFIX)) {
//                String channelId = headers.get(headName).get(0).substring(PREFIX.concat("-").length());
//                log.info("调用三方接口，渠道id：[{}]",channelId);
//                //根据渠道查询对应ak、sk
//                if (!isNumeric(channelId))
//                    throw new RuntimeException("渠道id有误");
//
//                SysChannelAuth sysChannelAuth = sysChannelAuthService.selectByChannelId(Long.valueOf(channelId));
                String AK = null;
                String SK = null;
                String[] value =  headers.get(headName).get(0).substring(PREFIX.concat(",").length()).split(",");
                if (value.length == 2) {
                    AK = value[0];
                    SK = value[1];
                }
                log.info("send request--AK:{},SK:{}",AK,SK);
                if (isAnyBlank(AK, SK))
                    throw new RuntimeException("该渠道不存在或渠道信息有误");

                long timestamp = Instant.now().getEpochSecond();
                String uuid = UUID.randomUUID().toString();

                StringJoiner joiner = new StringJoiner("\n", "", "\n")
                        .add(request.getMethod().name())
                        .add(request.getURI().getPath().toLowerCase())
                        .add(String.valueOf(timestamp))
                        .add(uuid);
                String authorization = "";
                try {
                    byte[] hmac = new HmacUtils(HMAC_SHA_256,SK.getBytes())
                            .hmac(joiner.toString().getBytes(StandardCharsets.UTF_8));

                    joiner = new StringJoiner(",")
                            .add(AK)
                            .add(String.valueOf(timestamp))
                            .add(uuid)
                            .add(encodeBase64String(hmac));
                    authorization = format("%s-%s-%s %s", "ROC", HMAC_SHA_256.getName(), VERSION, joiner.toString());
                    log.info("lake调用三方接口，Authorization: [{}]", authorization);
                } catch (Exception e) {
                    log.error("lake调用三方接口失败，[{}]", e.getMessage(), e);
                    throw e;
                }
                headers.set(AUTHORIZATION, authorization);
            }
        });
        return execution.execute(request, body);
    }
}